package com.bzkj.document.utils.purchaseorder;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.bzkj.common.domain.NccApiResponse;
import com.bzkj.document.mapper.WmsWareHouseInventoryMapper;
import com.bzkj.document.utils.common.DataProcessUtils;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * @projectName: prt-wms
 * @package: com.bzkj.document.utils.documentpublic.purchaseorder
 * @className: PurchaseOrderUtils
 * @description: 采购订单工具类
 * @author: C1309
 * @createDate: 2024年12月19日
 * @version: v1.0
 */
@Component
public class PurchaseOrderUtils {

    @Resource
    private WmsWareHouseInventoryMapper wareHouseInventoryMapper;

    @Resource
    @Qualifier("threadPoolTaskExecutor")
    private ThreadPoolTaskExecutor executor;

    // ==========================================================
    // 模块名称: 采购订单解析模块
    // 功能描述: 解析采购订单相关的业务逻辑
    // ==========================================================

    /**
     * 解析 NCC 采购订单
     *
     * @param nccApiResponse NCC 返回结果
     * @return 解析结果
     */
    public List<Map<String, Object>> processNccPurchaseOrderResponse(NccApiResponse nccApiResponse) {
        JSONArray dataArray = (nccApiResponse.getData() != null) ? nccApiResponse.getData() : new JSONArray();
        Map<String, Object>[] resultsArray = new Map[dataArray.size()];
        List<CompletableFuture<Void>> futures = new ArrayList<>();

        for (int i = 0; i < dataArray.size(); i++) {
            final int index = i;
            CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                try {
                    JSONObject dataObject = dataArray.getJSONObject(index);
                    JSONObject poOrder = dataObject.getJSONObject("pu.po_order");
                    if (poOrder == null) {
                        return;
                    }

                    Map<String, Object> header = parsePuPoOrder(poOrder);
                    JSONArray poOrderBodyList = dataObject.getJSONArray("pu.po_order_b");
                    if (poOrderBodyList == null || poOrderBodyList.isEmpty()) {
                        return;
                    }
                    List<Map<String, Object>> details = parsePuPoOrderBodyList(poOrderBodyList);

                    Map<String, Object> billData = new HashMap<>(2);
                    billData.put("header", header);
                    billData.put("details", details);
                    resultsArray[index] = billData;
                } catch (Exception e) {
                    // log.error("处理第 {} 条数据失败: {}", index, e.getMessage());
                }
            }, executor);

            futures.add(future);
        }

        CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();

        return Arrays.stream(resultsArray)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }


    /**
     * 解析NCC采购订单中的pu.po_order字段
     *
     * @param poOrder 采购订单对象
     * @return 返回结果
     */
    private ConcurrentHashMap<String, Object> parsePuPoOrder(JSONObject poOrder) {
        ConcurrentHashMap<String, Object> poOrderHeaderMap = new ConcurrentHashMap<>(11);

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        // cemployeeid(采购员)
        DataProcessUtils.processField(poOrder, poOrderHeaderMap, "cemployeeid");


        // pk_supplier(供应商)
        DataProcessUtils.processField(poOrder, poOrderHeaderMap, "pk_supplier");

        // dmakedate(制单日期)
        DataProcessUtils.handleDateField(poOrder, "dmakedate", sdf, poOrderHeaderMap);

        // dbilldate (订单日期)
        DataProcessUtils.handleDateField(poOrder, "dbilldate", sdf, poOrderHeaderMap);

        //订单编号
        DataProcessUtils.getStringField(poOrder, "vbillcode", poOrderHeaderMap);

        //采购部门最新版本
        DataProcessUtils.processField(poOrder, poOrderHeaderMap, "pk_dept");

        // taudittime (审批日期)
        DataProcessUtils.handleDateField(poOrder, "taudittime", sdf, poOrderHeaderMap);

        // 采购订单
        DataProcessUtils.getStringField(poOrder, "pk_order", poOrderHeaderMap);

        // 订单类型
        DataProcessUtils.getStringField(poOrder, "ctrantypeid", poOrderHeaderMap);

        // 订单类型编码
        DataProcessUtils.getStringField(poOrder, "vtrantypecode", poOrderHeaderMap);

        // 订单总数量
        DataProcessUtils.getFormattedDouble(poOrder, "ntotalastnum", poOrderHeaderMap);

        // vdef5 合同号
        DataProcessUtils.getStringField(poOrder, "vdef5", poOrderHeaderMap);

        return poOrderHeaderMap;
    }

    /**
     * 解析订单行数据列表
     *
     * @param poOrderBodyList 订单行 JSON 数组
     * @return 订单行解析结果列表
     */
    private List<Map<String, Object>> parsePuPoOrderBodyList(JSONArray poOrderBodyList) {
        List<Map<String, Object>> details = new ArrayList<>();
        for (int j = 0; j < poOrderBodyList.size(); j++) {
            JSONObject poOrderBody = poOrderBodyList.getJSONObject(j);
            details.add(parsingPuPoOrderB(poOrderBody));
        }
        return details;
    }

    /**
     * 解析NCC采购订单中的pu.po_order_b字段
     *
     * @param poOrderB pu.po_order_b数据
     * @return 解析结果
     */
    private HashMap<String, Object> parsingPuPoOrderB(JSONObject poOrderB) {
        HashMap<String, Object> puPoOrderBodyMap = new HashMap<>(10);

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        // pk_material 物料信息
        DataProcessUtils.processField(poOrderB, puPoOrderBodyMap, "pk_material");

        @SuppressWarnings("unchecked")
        HashMap<String, Object> pkMaterial = (HashMap<String, Object>) puPoOrderBodyMap.get("pk_material");

        // 查询物料的其他信息（保质期管理、批次管理、保质期单位、保质期）
        String pk = pkMaterial.get("pk").toString();
        HashMap<String, Object> additionMap = wareHouseInventoryMapper.selectAdditionalManagement(pk);
        puPoOrderBodyMap.put("additionMap", additionMap);
        // warehousePk是后面新加的
        List<HashMap<String, String>> wmsJwh = wareHouseInventoryMapper.selectNccWarehouse(pk, "");
        if (wmsJwh != null && !wmsJwh.isEmpty()) {
            String wmsWareHouse = wmsJwh.get(0).get("ncc_warehouse_id");
            puPoOrderBodyMap.put("wmsWareHouse", wmsWareHouse);
        } else {
            puPoOrderBodyMap.put("wmsWareHouse", null);
        }

        // 换算率
        DataProcessUtils.getStringField(poOrderB, "vchangerate", puPoOrderBodyMap);

        // nastnum 数量
        DataProcessUtils.getFormattedDouble(poOrderB, "nastnum", puPoOrderBodyMap);

        // nnum 主数量
        DataProcessUtils.getFormattedDouble(poOrderB, "nnum", puPoOrderBodyMap);
        double nnum = (double) puPoOrderBodyMap.get("nnum");
        puPoOrderBodyMap.put("nshouldnnum", nnum);
        puPoOrderBodyMap.remove("nnum");

        //来源单据表体主键
        DataProcessUtils.getStringField(poOrderB, "pk_order_b", puPoOrderBodyMap);

        // 行号
        DataProcessUtils.getStringField(poOrderB, "crowno", puPoOrderBodyMap);

        // 入库关闭（Y/N）
        DataProcessUtils.getStringField(poOrderB, "bstockclose", puPoOrderBodyMap);

        // castunitid 单位
        DataProcessUtils.processField(poOrderB, puPoOrderBodyMap, "castunitid");

        // cunitid 主单位
        DataProcessUtils.processField(poOrderB, puPoOrderBodyMap, "cunitid");

        // dbilldate 单据日期
        DataProcessUtils.handleDateField(poOrderB, "dbilldate", sdf, puPoOrderBodyMap);

        // dplanarrvdate 计划到货日期
        DataProcessUtils.handleDateField(poOrderB, "dplanarrvdate", sdf, puPoOrderBodyMap);

        // cproductorid 生产厂商
        DataProcessUtils.processField(poOrderB, puPoOrderBodyMap, "cproductorid");

        // pk_psfinanceorg_v 财务结算组织
        DataProcessUtils.processField(poOrderB, puPoOrderBodyMap, "pk_psfinanceorg_v");

        // pk_reqdept（需求部门）
        DataProcessUtils.processField(poOrderB, puPoOrderBodyMap, "pk_reqdept");

        //pk_supplier（供应商）
        DataProcessUtils.processField(poOrderB, puPoOrderBodyMap, "pk_supplier");

        // dplanarrvdate（计划收货日期）
        DataProcessUtils.handleDateField(poOrderB, "dplanarrvdate", sdf, puPoOrderBodyMap);

        // naccumstorenum(累计入库数量）
        DataProcessUtils.getFormattedDouble(poOrderB, "naccumstorenum", puPoOrderBodyMap);

        //vbdef1（申购部门）
        DataProcessUtils.processField(poOrderB, puPoOrderBodyMap, "vbdef1");

        // vbdef2（申请人）
        DataProcessUtils.processField(poOrderB, puPoOrderBodyMap, "vbdef2");

        //  vbdef6（供应商代码）
        DataProcessUtils.getStringField(poOrderB, "vbdef6", puPoOrderBodyMap);

        return puPoOrderBodyMap;
    }

    // ==========================================================
    // 模块名称: 采购入库单解析模块
    // 功能描述: 解析采购入库单相关的业务逻辑
    // ==========================================================

    /**
     * 解析NCC采购入库单
     *
     * @param nccApiResponse NCC返回的采购入库单数据
     * @return 解析结果
     */
    public List<Map<String, Object>> processNccInboundOrderResponse(NccApiResponse nccApiResponse) {
        JSONArray dataArray = (nccApiResponse.getData() != null) ? nccApiResponse.getData() : new JSONArray();
        Map<String, Object>[] resultsArray = new Map[dataArray.size()];
        List<CompletableFuture<Void>> futures = new ArrayList<>();

        for (int i = 0; i < dataArray.size(); i++) {
            final int index = i;
            CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                try {
                    JSONObject dataObject = dataArray.getJSONObject(index);
                    JSONObject purchaseInHead = dataObject.getJSONObject("ic.PurchaseInHeadVO");
                    if (purchaseInHead == null) {
                        return;
                    }
                    Map<String, Object> purchaseInHeader = parsePurchaseInHeadVO(purchaseInHead);

                    JSONArray purchaseInBodyList = dataObject.getJSONArray("ic.PurchaseInBodyVO");
                    if (purchaseInBodyList == null || purchaseInBodyList.isEmpty()) {
                        return;
                    }
                    List<Map<String, Object>> details = parsePurchaseInBodyVOList(purchaseInBodyList);

                    String vbillcode = purchaseInHeader.get("vbillcode").toString();
                    JSONObject cwarehouseid = (JSONObject) purchaseInHeader.get("cwarehouseid");
                    String cgeneralhid = purchaseInHeader.get("cgeneralhid").toString();

                    for (Map<String, Object> detail : details) {
                        detail.put("vbillcode", vbillcode);
                        detail.put("cwarehouseid", cwarehouseid);
                        detail.put("cgeneralhid", cgeneralhid);
                        detail.put("vtrantypecode",purchaseInHeader.get("vtrantypecode"));
                        if (purchaseInHeader.get("vsourcebillcode") == null) {
                            purchaseInHeader.put("vsourcebillcode", detail.get("vsourcebillcode"));
                        }
                    }

                    Map<String, Object> billDataMap = new HashMap<>(2);
                    billDataMap.put("header", purchaseInHeader);
                    billDataMap.put("details", details);
                    resultsArray[index] = billDataMap;
                } catch (Exception e) {
                    // log.error("处理第 {} 条数据失败: {}", index, e.getMessage());
                }
            }, executor);
            futures.add(future);
        }

        CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
        return Arrays.stream(resultsArray).filter(Objects::nonNull).collect(Collectors.toList());
    }

    /**
     * 解析采购入库头数据
     *
     * @param purchaseInHead 入库单头 JSON 对象
     * @return 订单头解析结果
     */
    private Map<String, Object> parsePurchaseInHeadVO(JSONObject purchaseInHead) {
        // 解析订单头逻辑
        HashMap<String, Object> purchaseInHeadVoMap = new HashMap<>(16);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // cgeneralhid（表头主键）
        DataProcessUtils.getStringField(purchaseInHead, "cgeneralhid", purchaseInHeadVoMap);

        // vbillcode（单据编号）
        DataProcessUtils.getStringField(purchaseInHead, "vbillcode", purchaseInHeadVoMap);

        // dmakedate（制单日期）
        DataProcessUtils.handleDateField(purchaseInHead, "dmakedate", sdf, purchaseInHeadVoMap);
        // cvendorid（供应商）
        DataProcessUtils.processField(purchaseInHead, purchaseInHeadVoMap, "cvendorid");
        // ctrantypeid（出入库类型）
        DataProcessUtils.getStringField(purchaseInHead, "ctrantypeid", purchaseInHeadVoMap);
        // cfanaceorgvid（财务结算组织）
        DataProcessUtils.processField(purchaseInHead, purchaseInHeadVoMap, "cfanaceorgvid");

        // fbillflag（单据状态）
        DataProcessUtils.getStringField(purchaseInHead, "fbillflag", purchaseInHeadVoMap);

        // vtrantypecode（出入库类型编码）
        DataProcessUtils.getStringField(purchaseInHead, "vtrantypecode", purchaseInHeadVoMap);

        //cdptid（采购部门最新版本）
        DataProcessUtils.processField(purchaseInHead, purchaseInHeadVoMap, "cdptid");

        // cbizid（采购员）
        DataProcessUtils.processField(purchaseInHead, purchaseInHeadVoMap, "cbizid");

        // fbuysellflag(购销类型）
        DataProcessUtils.getStringField(purchaseInHead, "fbuysellflag", purchaseInHeadVoMap);

        // freplenishflag（采购退库）
        DataProcessUtils.getStringField(purchaseInHead, "freplenishflag", purchaseInHeadVoMap);

        // ntotalnum（总数量）
        DataProcessUtils.getFormattedDouble(purchaseInHead, "ntotalnum", purchaseInHeadVoMap);

        // creator(创建人）
        DataProcessUtils.processField(purchaseInHead, purchaseInHeadVoMap, "creator");

        // vdef49(WMS单据号)
        DataProcessUtils.getStringField(purchaseInHead, "vdef49", purchaseInHeadVoMap);

        // vdef50(WMS单据号)
        DataProcessUtils.getStringField(purchaseInHead, "vdef50", purchaseInHeadVoMap);
        String vdef50 = purchaseInHead.getString("vdef50");

        // cwarehouseid（仓库）
        DataProcessUtils.processField(purchaseInHead, purchaseInHeadVoMap, "cwarehouseid");

        //corpoid(公司信息）
        DataProcessUtils.processField(purchaseInHead, purchaseInHeadVoMap, "corpoid");

        // modifier(修改人）
        DataProcessUtils.processField(purchaseInHead, purchaseInHeadVoMap, "modifier");

        //modifiedtime (修改时间）
        DataProcessUtils.handleDateField(purchaseInHead, "modifiedtime", sdf, purchaseInHeadVoMap);

        // cpurorgoid(采购组织）
        DataProcessUtils.processField(purchaseInHead, purchaseInHeadVoMap, "cpurorgoid");

        // cpurorgvid（采购组织最新版本）
        DataProcessUtils.processField(purchaseInHead, purchaseInHeadVoMap, "cpurorgvid");

        //dbilldate（单据日期）
        DataProcessUtils.handleDateField(purchaseInHead, "dbilldate", sdf, purchaseInHeadVoMap);

        //ntotalpiece（总件数）
        DataProcessUtils.getFormattedDouble(purchaseInHead, "ntotalpiece", purchaseInHeadVoMap);

        //cwhsmanagerid（库管员）
        DataProcessUtils.processField(purchaseInHead, purchaseInHeadVoMap, "cwhsmanagerid");

        //creationtime（创建时间）
        DataProcessUtils.handleDateField(purchaseInHead, "creationtime", sdf, purchaseInHeadVoMap);

        // vdef5(OA合同号）
        DataProcessUtils.getStringField(purchaseInHead, "vdef5", purchaseInHeadVoMap);

        // vsourcebillcode(采购订单号）
        DataProcessUtils.getStringField(purchaseInHead, "vsourcebillcode", purchaseInHeadVoMap);


        // billmaker(制单人）
        DataProcessUtils.processField(purchaseInHead, purchaseInHeadVoMap, "billmaker");

        // vbcdef2（供应商代码）
        DataProcessUtils.getStringField(purchaseInHead, "vbcdef2", purchaseInHeadVoMap);

        // vbcdef3（包材版本）
        DataProcessUtils.getStringField(purchaseInHead, "vbcdef3", purchaseInHeadVoMap);

        return purchaseInHeadVoMap;
    }


    /**
     * 解析采购入库单行数据列表
     *
     * @param purchaseInBodyList 订单行 JSON 数组
     * @return 订单行解析结果列表
     */
    private List<Map<String, Object>> parsePurchaseInBodyVOList(JSONArray purchaseInBodyList) {
        List<Map<String, Object>> details = new ArrayList<>();
        for (int j = 0; j < purchaseInBodyList.size(); j++) {
            JSONObject purchaseInBody = purchaseInBodyList.getJSONObject(j);
            details.add(parsingPurchaseInBody(purchaseInBody));
        }
        return details;
    }

    /**
     * 解析采购入库单行数据
     *
     * @param purchaseInBody 采购入库单行数据
     * @return 解析结果
     */
    private Map<String, Object> parsingPurchaseInBody(JSONObject purchaseInBody) {
        HashMap<String, Object> purchaseInHeadVoMap = new HashMap<>(32);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        // cgeneralbid
        String cgeneralbid = purchaseInBody.getString("cgeneralbid");
        if (cgeneralbid != null) {
            purchaseInHeadVoMap.put("cgeneralbid", cgeneralbid);
        }
        // cmaterialoid--物料
        DataProcessUtils.processField(purchaseInBody, purchaseInHeadVoMap, "cmaterialoid");

        // nshouldassistnum--应收辅数量
        DataProcessUtils.getFormattedDouble(purchaseInBody, "nshouldassistnum", purchaseInHeadVoMap);

        // nshouldnum--应收主数量
        DataProcessUtils.getFormattedDouble(purchaseInBody, "nshouldnum", purchaseInHeadVoMap);

        // vqtunitratencc--报价换算系数
        DataProcessUtils.getStringField(purchaseInBody, "vqtunitratencc", purchaseInHeadVoMap);

        // vchangerate--换算系数
        DataProcessUtils.getStringField(purchaseInBody, "vchangerate", purchaseInHeadVoMap);

        // nassistnum--实收辅数量
        DataProcessUtils.getFormattedDouble(purchaseInBody, "nassistnum", purchaseInHeadVoMap);

        // nnum--实收主数量
        DataProcessUtils.getFormattedDouble(purchaseInBody, "nnum", purchaseInHeadVoMap);

        // castunitid--辅单位
        DataProcessUtils.processField(purchaseInBody, purchaseInHeadVoMap, "castunitid");

        // cunitid--主单位
        DataProcessUtils.processField(purchaseInBody, purchaseInHeadVoMap, "cunitid");

        // crowno--行号
        DataProcessUtils.getStringField(purchaseInBody, "crowno", purchaseInHeadVoMap);

        // cstateid--库存状态
        DataProcessUtils.getStringField(purchaseInBody, "cstateid", purchaseInHeadVoMap);

        // csourcetranstype
        DataProcessUtils.getStringField(purchaseInBody, "csourcetranstype", purchaseInHeadVoMap);

        // csourcetype
        DataProcessUtils.getStringField(purchaseInBody, "csourcetype", purchaseInHeadVoMap);

        //vsourcebillcode
        DataProcessUtils.getStringField(purchaseInBody, "vsourcebillcode", purchaseInHeadVoMap);

        // csourcebillhid
        DataProcessUtils.getStringField(purchaseInBody, "csourcebillhid", purchaseInHeadVoMap);

        // csourcebillbid
        DataProcessUtils.getStringField(purchaseInBody, "csourcebillbid", purchaseInHeadVoMap);

        // pk_batchcode
        DataProcessUtils.getStringField(purchaseInBody, "pk_batchcode", purchaseInHeadVoMap);

        // vvendbatchcode
        DataProcessUtils.getStringField(purchaseInBody, "vvendbatchcode", purchaseInHeadVoMap);

        // vbatchcode
        DataProcessUtils.getStringField(purchaseInBody, "vbatchcode", purchaseInHeadVoMap);

        // vbatchcodenote
        DataProcessUtils.getStringField(purchaseInBody, "vbatchcodenote", purchaseInHeadVoMap);

        //nvolume
        DataProcessUtils.getFormattedDouble(purchaseInBody, "nvolume", purchaseInHeadVoMap);

        // nweight
        DataProcessUtils.getFormattedDouble(purchaseInBody, "nweight", purchaseInHeadVoMap);

        // dproducedate
        DataProcessUtils.handleDateField(purchaseInBody, "dproducedate", sdf, purchaseInHeadVoMap);

        //dvalidate
        DataProcessUtils.handleDateField(purchaseInBody, "dvalidate", sdf, purchaseInHeadVoMap);

        //dbizdate
        DataProcessUtils.handleDateField(purchaseInBody, "dbizdate", sdf, purchaseInHeadVoMap);

        // vbdef48（复验期）
        DataProcessUtils.getStringField(purchaseInBody, "vbdef48", purchaseInHeadVoMap);

        // vbdef49
        DataProcessUtils.getStringField(purchaseInBody, "vbdef49", purchaseInHeadVoMap);

        // vbdef50
        DataProcessUtils.getStringField(purchaseInBody, "vbdef50", purchaseInHeadVoMap);

        // cvendorid
        DataProcessUtils.processField(purchaseInBody, purchaseInHeadVoMap, "cvendorid");

        // cproductorid
        DataProcessUtils.processField(purchaseInBody, purchaseInHeadVoMap, "cproductorid");

        // vbcdef2（供应商代码）
        DataProcessUtils.getStringField(purchaseInBody, "vbcdef2", purchaseInHeadVoMap);

        // vbcdef3（包材版本）
        DataProcessUtils.getStringField(purchaseInBody, "vbcdef3", purchaseInHeadVoMap);

        // cmaterialvid
        DataProcessUtils.processField(purchaseInBody, purchaseInHeadVoMap, "cmaterialvid");


        @SuppressWarnings("unchecked")
        HashMap<String, Object> pkMaterial = (HashMap<String, Object>) purchaseInHeadVoMap.get("cmaterialvid");

        // 查询物料的其他信息（保质期管理、批次管理、保质期单位、保质期）
        String pk = pkMaterial.get("pk").toString();
        HashMap<String, Object> additionMap = wareHouseInventoryMapper.selectAdditionalManagement(pk);
        purchaseInHeadVoMap.put("additionMap", additionMap);
        return purchaseInHeadVoMap;
    }
}
